package org.pentaho.obs.vfs;

import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.provider.AbstractFileName;
import org.pentaho.di.core.logging.LogChannel;
import org.pentaho.di.core.logging.LogChannelInterface;
import org.pentaho.di.core.util.StorageUnitConverter;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.obscommon.OBSCommonFileSystem;
import org.pentaho.obscommon.OBSKettleProperty;

public class OBSFileSystem extends OBSCommonFileSystem {

    private static final Class<?> PKG = OBSFileSystem.class;
    private static final LogChannelInterface consoleLog = new LogChannel( BaseMessages.getString( PKG, "TITLE.OBSFile" ) );

    protected StorageUnitConverter storageUnitConverter;
    protected OBSKettleProperty obsKettleProperty;

    private static final String MIN_PART_SIZE = "5MB";

    private static final String MAX_PART_SIZE = "5GB";

    protected OBSFileSystem( final FileName rootName, final FileSystemOptions fileSystemOptions ) {
        this( rootName, fileSystemOptions, new StorageUnitConverter(), new OBSKettleProperty() );
    }

    protected OBSFileSystem( final FileName rootName, final FileSystemOptions fileSystemOptions,
                            final StorageUnitConverter storageUnitConverter, final OBSKettleProperty obsKettleProperty ) {
        super( rootName, fileSystemOptions );
        this.storageUnitConverter = storageUnitConverter;
        this.obsKettleProperty = obsKettleProperty;
    }

    protected FileObject createFile( AbstractFileName name ) throws Exception {
        return new OBSFileObject( name, this );
    }

    public int getPartSize() {
        long parsedPartSize = parsePartSize( obsKettleProperty.getPartSize() );
        return convertToInt( parsedPartSize );
    }

    protected long parsePartSize( String partSizeString ) {
        long parsePartSize = convertToLong( partSizeString );
        if ( parsePartSize < convertToLong( MIN_PART_SIZE ) ) {
            consoleLog.logBasic( BaseMessages.getString( PKG, "WARN.OBSMultiPart.DefaultPartSize", partSizeString, MIN_PART_SIZE ) );
            parsePartSize = convertToLong( MIN_PART_SIZE );
        }

        // still allow > 5GB, api might be updated in the future
        if ( parsePartSize > convertToLong( MAX_PART_SIZE ) ) {
            consoleLog.logBasic( BaseMessages.getString( PKG, "WARN.OBSMultiPart.MaximumPartSize", partSizeString, MAX_PART_SIZE ) );
        }
        return parsePartSize;
    }

    protected int convertToInt( long parsedPartSize ) {
        return (int) Long.min( Integer.MAX_VALUE, parsedPartSize );
    }

    protected long convertToLong( String partSize ) {
        return storageUnitConverter.displaySizeToByteCount( partSize );
    }
}
